﻿/*
 * QWFP (QWine For Pajak)
 * Copyright (C) 2010 Wish Enterprise

 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * Contact Us:
 * E-Mail   : contact@wishenterprise.com
 * Website  : http://www.wishenterprise.com
 * Telp.    : 0276 - 3339945
 * Mobile   : 0815 4850 3620
 * 
 * */
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace QWTouchPanel
{
    /// <summary>
    /// Raw Printer Helper 
    /// </summary>
    public class RawPrinterHelper
    {
        /// <summary>
        /// Opens the printer.
        /// </summary>
        /// <param name="szPrinter">The sz printer.</param>
        /// <param name="hPrinter">The h printer.</param>
        /// <param name="pd">The pd.</param>
        /// <returns></returns>
        [DllImport("winspool.Drv",
            EntryPoint = "OpenPrinterA",
            SetLastError = true,
            CharSet = CharSet.Ansi,
            ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool OpenPrinter(
            [MarshalAs(UnmanagedType.LPStr)] string szPrinter,
            out IntPtr hPrinter,
            IntPtr pd);

        /// <summary>
        /// Closes the printer.
        /// </summary>
        /// <param name="hPrinter">The h printer.</param>
        /// <returns></returns>
        [DllImport("winspool.Drv",
            EntryPoint = "ClosePrinter",
            SetLastError = true,
            ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool ClosePrinter(
            IntPtr hPrinter);

        /// <summary>
        /// Starts the doc printer.
        /// </summary>
        /// <param name="hPrinter">The h printer.</param>
        /// <param name="level">The level.</param>
        /// <param name="di">The di.</param>
        /// <returns></returns>
        [DllImport("winspool.Drv",
            EntryPoint = "StartDocPrinterA",
            SetLastError = true,
            CharSet = CharSet.Ansi,
            ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartDocPrinter(
            IntPtr hPrinter, Int32 level,
            [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

        /// <summary>
        /// Ends the doc printer.
        /// </summary>
        /// <param name="hPrinter">The h printer.</param>
        /// <returns></returns>
        [DllImport("winspool.Drv",
            EntryPoint = "EndDocPrinter",
            SetLastError = true,
            ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(
            IntPtr hPrinter);

        /// <summary>
        /// Starts the page printer.
        /// </summary>
        /// <param name="hPrinter">The h printer.</param>
        /// <returns></returns>
        [DllImport("winspool.Drv",
            EntryPoint = "StartPagePrinter",
            SetLastError = true, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(
            IntPtr hPrinter);

        /// <summary>
        /// Ends the page printer.
        /// </summary>
        /// <param name="hPrinter">The h printer.</param>
        /// <returns></returns>
        [DllImport("winspool.Drv",
            EntryPoint = "EndPagePrinter",
            SetLastError = true,
            ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(
            IntPtr hPrinter);

        /// <summary>
        /// Writes the printer.
        /// </summary>
        /// <param name="hPrinter">The h printer.</param>
        /// <param name="pBytes">The p bytes.</param>
        /// <param name="dwCount">The dw count.</param>
        /// <param name="dwWritten">The dw written.</param>
        /// <returns></returns>
        [DllImport("winspool.Drv",
            EntryPoint = "WritePrinter",
            SetLastError = true,
            ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool WritePrinter(
            IntPtr hPrinter,
            IntPtr pBytes,
            Int32 dwCount,
            out Int32 dwWritten);

        /// <summary>
        /// Sends the bytes to printer.
        /// </summary>
        /// <param name="szPrinterName">Name of the sz printer.</param>
        /// <param name="pBytes">The p bytes.</param>
        /// <param name="dwCount">The dw count.</param>
        /// <returns></returns>
        public static bool SendBytesToPrinter(
            string szPrinterName,
            IntPtr pBytes,
            Int32 dwCount)
        {
            Int32 dwError = 0, dwWritten = 0;

            var hPrinter = new IntPtr(0);

            var di = new DOCINFOA();

            bool bSuccess = false;

            di.pDocName = "QWFP - Print Nomor Antrian";

            di.pDataType = "RAW";

            if (OpenPrinter(
                szPrinterName.Normalize(),
                out hPrinter, IntPtr.Zero))
            {
                if (StartDocPrinter(hPrinter, 1, di))
                {
                    if (StartPagePrinter(hPrinter))
                    {
                        bSuccess =
                            WritePrinter(
                                hPrinter,
                                pBytes,
                                dwCount,
                                out dwWritten);

                        EndPagePrinter(hPrinter);
                    }

                    EndDocPrinter(hPrinter);
                }

                ClosePrinter(hPrinter);
            }

            if (bSuccess == false)
            {
                dwError =
                    Marshal.GetLastWin32Error();
            }

            return bSuccess;
        }

        /// <summary>
        /// Sends the file to printer.
        /// </summary>
        /// <param name="szPrinterName">Name of the sz printer.</param>
        /// <param name="szFileName">Name of the sz file.</param>
        /// <returns></returns>
        public static bool SendFileToPrinter(
            string szPrinterName,
            string szFileName)
        {
            var fs =
                new FileStream(szFileName, FileMode.Open);

            var br =
                new BinaryReader(fs);

            var bytes =
                new Byte[fs.Length];

            bool bSuccess =
                false;

            var pUnmanagedBytes =
                new IntPtr(0);

            int nLength =
                Convert.ToInt32(fs.Length);

            bytes = br.ReadBytes(nLength);

            pUnmanagedBytes =
                Marshal.AllocCoTaskMem(nLength);

            Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);

            bSuccess =
                SendBytesToPrinter(
                    szPrinterName,
                    pUnmanagedBytes,
                    nLength);

            Marshal.FreeCoTaskMem(pUnmanagedBytes);

            return bSuccess;
        }


        /// <summary>
        /// Sends the string to printer.
        /// </summary>
        /// <param name="szPrinterName">Name of the sz printer.</param>
        /// <param name="szString">The sz string.</param>
        /// <returns></returns>
        public static bool SendStringToPrinter(
            string szPrinterName,
            string szString)
        {
            IntPtr pBytes;

            Int32 dwCount;

            dwCount =
                szString.Length;

            pBytes =
                Marshal.StringToCoTaskMemAnsi(szString);

            SendBytesToPrinter(
                szPrinterName,
                pBytes,
                dwCount);

            Marshal.FreeCoTaskMem(pBytes);

            return true;
        }

        #region Nested type: DOCINFOA

        /// <summary>
        /// DOCINFOA
        /// </summary>
        [StructLayout(LayoutKind.Sequential,
            CharSet = CharSet.Ansi)]
        public class DOCINFOA
        {
            /// <summary>
            /// pDocName
            /// </summary>
            [MarshalAs(UnmanagedType.LPStr)] public string pDocName;

            /// <summary>
            /// pOutputFile
            /// </summary>
            [MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;

            /// <summary>
            /// pDataType
            /// </summary>
            [MarshalAs(UnmanagedType.LPStr)] public string pDataType;
        }

        #endregion
    }
}